home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
ctut.arc
/
LESSON12
< prev
next >
Wrap
Text File
|
1986-02-13
|
6KB
|
161 lines
.NT
A NOTE ABOUT THE LESSONS in C
.b4-24R5C4
These were written while the author was ~Ilearning~N the language and since
.R6C4
they are ~Ifree~N ( to copy and/or distribute ) there is a money-back
.R7C4
guarantee on the accuracy of each and every statement in the lessons (!)
.R9C4
The ~Idisplay~N program was written ( in C ) in order to provide a vehicle
.R10C4
for displaying the lessons.
.R12C5
.B
P.J.Ponzo
.B
Dept. of Applied Math
.B
Univ. of Waterloo
.B
Ontario N2L 3G1
.K16,32
PonzoTUTOR
.WNT
FIELDS
.R5C1
Suppose we wish to manipulate the results of a questionnaire containing
20 questions with answers either YES or NO. If we store the answers in an
~n~Iint~Neger variable ~b~Ix~N, with x=1 corresponding to a YES answer and
x=0 to a NO, then (since integers occupy 2 bytes of memory, usually) this
would require 40 bytes per questionnaire and, if 1000 people answered the
questionnaire the results would occupy 40,000 bytes ... too much!!
~ISO~N, we store the answers in a 1-byte ~b~Ichar~Nacter variable ~b~Ix~N with
either x='Y' or x='N. That would take 20,000 bytes of memory ... too much!
~ISO~N (since 1=YES and 0=NO only needs ~I1 bit~N of memory) we store the
results in 20,000 ~Ibits~N ... let's see ... at 8 bits per byte that would
take ... 20000/8=~I2500~N bytes ... just right.
Is there a DATA TYPE called ~b~Ibit~N (so we could declare ~b~Ibit x;~N) ?
Alas, there is NOT ... but we ~Ican~N create a ~Istructure~N with members which
occupy ~Ibits~N of memory!
.WN
~b~I struct byte { /* define a structure called byte */ ~N
~b~I unsigned member1 : 1; /* member occupies 1 bit */ ~N
~b~I unsigned member2 : 4; /* member occupies 4 bits */ ~N
~b~I unsigned member3 : 3; /* member occupies 3 bits */ ~N
~b~I } x; /* declare x to be such a structure */ ~N
Now ~b~Ix~N is a structure of type ~b~Ibyte~N which has 3 members (in this example).
Each member is an ~b~Iunsigned~N integer.
These members are made to occupy a number of ~Ibits~N.
The colon ~b~I : ~N followed by an integer (like 1,4 and 3) arranges this for
us.
Now we can (as usual) refer to ~b~Ix.member1~N, ~b~Ix.member2~N and ~b~Ix.member3~N
and (for example) say: ~b~Ix.member1=0;~N or ~b~Ix.member2=13;~N, etc.
Since ~b~Ix.member1~N is 1 bit wide, it will hold numbers 0 and 1 only.
Since ~b~Ix.member2~N is 4 bits wide, it will hold numbers 0,1,2,..., 15.
Since ~b~Ix.member3~N is 3 bits wide, it will hold numbers 0,1,2,..,7.
.w
... and the whole structure, with all 3 members, only fills one byte of
memory (since 1+4+3 bits =1 byte).
~IThe members, occupying a number of adjacent bits in memory, are called~N
~V FIELDS ~N
.WN
If we define another struct called bytes, and declare *x ...
~b~I struct bytes { /* define a structure called bytes */ ~N
~b~I unsigned member1 : 1; /* member occupies 1 bit */ ~N
~b~I unsigned member2 : 4; /* member occupies 4 bits */ ~N
~b~I unsigned member3 : 4; /* member occupies 3 bits */ ~N
~b~I } *x; /* declare x to be a pointer */ ~N
so that ~b~Ix~N is now a ~r~Ipointer~N to a structure, then we would access
a member with: ~b~Ix->member1~N (remember?)
If you're really squeezed for memory space, then cram as much into a
2-byte integer as possible by using ~Ibits~N.
Note that, in the above structure, we now have 1+4+4 bits which is more
than a byte will hold, so the compiler will put ~b~Imember3~N into a
second byte (and "waste" the remaining 3 bits of the first byte and
probably the remaining 4 bits of the second byte too!)
.K17,32
8bits/byte
.WNT
UNIONS
.R5C1
If you're still in need of memory space you can arrange to have several
variables occupy the ~Isame~N memory space ... but not at the same time
(of course).
This union of variables is called a ... ~V UNION ~N (what else?)
~b~I union sam { /* define a union called sam */ ~N
~b~I int x; /* the first member is an int */ ~N
~b~I float y; /* the second member is a float */ ~N
~b~I char z; /* the third member is a char */ ~N
~b~I } jeckyl, *hyde; /* declare some unions */ ~N
Since these 3 variables ~b~Ix~N, ~b~Iy~N and ~b~Iz~N occupy different amounts
of memory the variable ~b~Ijeckyl~N will occupy sufficient memory to hold
the largest of ~b~Ix~N, ~b~Iy~N and ~b~Iz~N (in this case, it's ~b~Iy~N).
You may point to a union ( ~b~Ihyde~N is a ~r~Ipointer~N)
and/or access one of its members ( ~b~Ijeckyl.x=123~N or ~b~Ihyde->z='A'~N ).
.WN
~b~I union sam { /* define a union called sam */ ~N
~b~I int x; /* the first member is an int */ ~N
~b~I float y; /* the second member is a float */ ~N
~b~I char z; /* the third member is a char */ ~N
~b~I } jeckyl, *hyde; /* declare some unions */ ~N
If you say: ~b~Ijeckyl.x=123~N ( an integer ) then the space set aside for
~b~Ijeckyl~N will be occupied (in part) by the integer ~b~I123~N.
If you then say: ~b~Iprintf("%f",jeckyl.y);~N the printf function will go
to the memory location where jeckyl lives, interpret the 2-byte ~b~Iint~N
~I123~N as a 7-byte float ('cause we said ~b~I%f~N) and print garbage!
.K19,60
MORAL?
.W
~V ~N
~V jeckyl and *hyde will contain an int, float or char depending upon ~N
~V whether the last thing you put there was an int, float or char! ~N
~V ~N
.WN
So, keep track with some variable called WhoThere.
~b~I#define CHAR 1 ~N
~b~I#define INTEGER 2 ~N
~b~I#define FLOAT 3 ~N
~b~I .................. ~N
~b~Iint WhoThere; ~N
~b~I .................. ~N
Each time you say:
~b~Ihyde->y=12.34;~N then also say: ~b~IWhoThere=FLOAT;~N
so you can check if ~b~IWhoThere==CHAR~N or ~b~IWhoThere==INTEGER~N etc.
to see who's currently a member of this union!
.K3,60
easy eh?
.WN
.T
That's all folks!
.K16,32
au revoir!
.q